/*
 * GraphDrawer.h
 *
 *  Created on: 2018年9月2日
 *      Author: zhengboyuan
 */

#ifndef SRC_GRAPHDRAWER_H_
#define SRC_GRAPHDRAWER_H_

#include "BasicType.h"
#include "VideoWindow.h"
#include "SDL.h"
#include <string>
#include <vector>
#include "TCriticalSection.h"
#include "MutablePen.h"


typedef std::vector< POINT >	Points;

class GraphDrawer
{
public:
	GraphDrawer();
	virtual ~GraphDrawer();

    void enableDrawGraph(int mode);

    void setDrawGraph(const char* value, size_t size, const SIZE& winSize, const RECT& rcVideo, int width, int height);

    const char* getDrawGraph(const SIZE& winSize, const RECT& rcVideo, int width, int height);

    bool isDrawEnabled();

    int getMode();

    bool getRect(SDL_Rect& rect);

    bool getPolygon(Points& points);

    void mouseButtonDown(int which, int x, int y, int modifier);
    void mouseButtonUp(int which, int x, int y);
    void mouseMove(int x, int y);
    void mouseButtonDblClick(int which, int x, int y);
    void winSizeChanged(int width, int height);


    void clear();

    bool hasRect();

    void draw(HWND hwnd, HDC hdc, const RECT& rcWin, const RECT& rcDest, int width, int height);

	void removeRect();
	void removePolygon();

public:
	static void mapPoint(SIZE prevSize, SIZE size, SDL_Point& point);
	static void mapRect(SIZE prevSize, SIZE size, SDL_Rect& rect);
	static void mapPoints(SIZE prevSize, SIZE size, Points& points);

	/// 从窗口坐标映射到视频坐标
	static void mapPoint(const SIZE& winSize, const RECT& rcVideo, SDL_Point& point);
	static void mapPoint(const SIZE& winSize, const RECT& rcVideo, POINT& point);
	static void mapRect(const SIZE& winSize, const RECT& rcVideo, SDL_Rect& rect);
	static void mapPoint(const SIZE& winSize, const RECT& rcVideo, Points& points);

	static void rmapPoint(const SIZE& winSize, const RECT& rcVideo, SDL_Point& point);
	static void rmapPoint(const SIZE& winSize, const RECT& rcVideo, POINT& point);
	static void rmapRect(const SIZE& winSize, const RECT& rcVideo, SDL_Rect& rect);
	static void rmapPoint(const SIZE& winSize, const RECT& rcVideo, Points& points);

	/// 判断线段是否交叉
	static bool isLineCross(const POINT& a, const POINT& b, const POINT& c, const POINT& d);
	static bool isLineCross(const Points& points, const POINT& pt);
	static bool isLineCross(const POINT* points, int size, const POINT& pt);

	static int pnpoly(const Points& points, const POINT& pt);
	static bool isInPolygon(const Points& points, const POINT& pt);
	static bool isInPolygonRect(const Points& points, const POINT& pt);
	static bool isInPolygonRect(const Points& points, const POINT& pt, int radius);
	static RECT enclosePoints(const Points& points);

	static bool containsRect(const RECT& src, const RECT& rc);
	static bool hasIntersection(const RECT& src, const RECT& rc);
	static SDL_Rect subtractRect(const RECT& src, const RECT& rc);

	static SDL_Rect inflateRect(const SDL_Rect& rc, int step);
	static RECT inflateRect(const RECT& rc, int step);

	static RECT toRect(const SDL_Rect& rc);

	static bool willCross(const Points& polygon, const POINT& pt);
	static bool isLineCross(const Points& polygon);

protected:
    bool isRectEmpty();


    void drawFoldPoint(HDC hdc, int x, int y, int radius, HBRUSH brush);
    void drawFoldPoint(HDC hdc, const POINT& point, int radius, HBRUSH brush);

    void drawFoldPoint(HDC hdc, Points& points, int radius, HBRUSH brush);
    void drawFoldPoint(HDC hdc, POINT* points, int size, int radius, HBRUSH brush);


    

    SDL_Rect getFoldPointRect(const SDL_Point& point, int radius);

    bool hitFoldPoint(const SDL_Point& point, const SDL_Point& foldPoint, int radius);
    bool hitFoldPoint(const SDL_Point& point, const POINT& foldPoint, int radius);

    bool hitFoldPoint(const SDL_Point& point, const SDL_Rect& rc, int radius, SDL_Point& beginPoint, SDL_Point& endPoint);

    int hitFoldPoint(const POINT& point, const Points& points, int radius, SDL_Point& foldPoint);


    bool isSameFolePoint(const SDL_Point& first, const SDL_Point& second, int radius);

    void adjustPolygon();

    Points trimCrossLine(const Points& polygon);

    void adjustIntersect();

	bool checkEditRect(int which, int x, int y, int modifier);
	bool checkEditPolygon(int which, int x, int y, int modifier);

protected:
    comn::CriticalSection	m_cs;

    int	m_drawMode;

    std::string m_json;

    /// rect
    SDL_Rect	m_rect;

    SDL_Point	m_beginPoint;
    SDL_Point	m_endPoint;
    bool	m_drawingRect;

    bool	m_rectActive;

    MutablePen	m_rectPen;
    HBRUSH	m_rectBbrush;

    SIZE	m_winSize;
    bool	m_mousePressed;

    Points	m_polygon;
    bool	m_drawingPolygon;
    bool	m_polyActive;
    int		m_polyIndex;
	POINT	m_polyPoint;

    MutablePen	m_polyPen;
    HBRUSH	m_polyBbrush;

    RECT	m_videoRect;
    SIZE	m_videoSize;

};



#endif /* SRC_GRAPHDRAWER_H_ */
